package com.citrix.gs.kit;

import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.perforce.p4java.core.IDepot;
import com.perforce.p4java.core.file.FileSpecBuilder;
import com.perforce.p4java.core.file.FileSpecOpStatus;
import com.perforce.p4java.core.file.IFileSpec;
import com.perforce.p4java.exception.AccessException;
import com.perforce.p4java.exception.ConnectionException;
import com.perforce.p4java.exception.P4JavaException;
import com.perforce.p4java.option.server.GetDepotFilesOptions;
import com.perforce.p4java.server.IOptionsServer;
import com.perforce.p4java.server.ServerFactory;

public class PerforceKit {
    
    private static Logger logger = LoggerFactory.getLogger(PerforceKit.class);
            
    public static IOptionsServer getPerforceServer(String server, String userName, String password) {
        
        IOptionsServer perforceServer = null;
        
        try{
            perforceServer = ServerFactory.getOptionsServer(String.format("p4java://%s", server), null);
            if(perforceServer != null) {
                perforceServer.connect();
                perforceServer.setUserName(userName);
                perforceServer.login(password);
            } 
            
        } catch(Exception e) {
            logger.error("Init config server fail: ", e);
            releasePerforceServer(perforceServer);
        }
        
        return perforceServer;  
    }
    
    public static boolean releasePerforceServer(IOptionsServer perforceServer){
        if(perforceServer != null) {
            try {
                perforceServer.disconnect();
            } catch (Exception e) {
                logger.error("Disconnect perforce server fail: ", e);
            }finally {
                perforceServer = null;
            }
        }
        
        return true;
    }
    
    public static Document getXmlAsDoc(IOptionsServer perforceServer, String path) {
        
        Document doc = null;
        
        try {
            
            List<IFileSpec> fileList = perforceServer.getDepotFiles(
                    FileSpecBuilder.makeFileSpecList(path), new GetDepotFilesOptions());
            
            if(fileList != null && fileList.size() == 1 && fileList.get(0).getOpStatus() == FileSpecOpStatus.VALID) {
                
                SAXReader reader = new SAXReader();
                doc = reader.read(fileList.get(0).getContents(true));

                
            } else {
                logger.error("Xml file: {} could not be found", path);
            }
            
        } catch (P4JavaException e) {
            logger.error("Fail to get xml file: {}" , path, e);
        } catch (DocumentException e) {
            logger.error("Fail to read xml file");
        }
        
        return doc;
    }
    
    public static boolean validatePath(IOptionsServer perforceServer, String path) {
        
        try {

            if(!path.endsWith("...")) {
                logger.error("The perforce path is not ends with ... is not supported to be validated");
                return false;
            }
            
            if(!(path.startsWith("//") || path.startsWith("-//"))) {
                logger.error("The perforce path is not start with // or -// is not validated");
                return false;
            }
            
            if(path.startsWith("-//")){
                path = path.substring(1);
            }
            
            String depotName = path.split("/")[2];
            IDepot depot = perforceServer.getDepot(depotName);
            
            if(depot == null) {
                logger.error("The depot {} in path {} does not exist", depotName, path);
                return false;
            }
            
            
            List<IFileSpec> dirSpecs = FileSpecBuilder.makeFileSpecList(path.split("/\\.\\.\\.")[0]);
            List<IFileSpec> dirList = perforceServer.getDirectories(dirSpecs, null);
            
            if(dirList == null || !(dirList.stream().map(d -> {
                return d != null && d.getOpStatus() == FileSpecOpStatus.VALID;
            }).reduce((r1, r2) -> r1&&r2).get())) {
                
                logger.error("The directory specified in path {} could not be found", path);
                return false;
            }
            
            
            /*
            List<IFileSpec> fileSpecs = FileSpecBuilder.makeFileSpecList(path);
            
            fileSpecs.forEach(System.out::println);
            
            System.out.println("");
            
            List<IFileSpec> fileList = perforceServer.getDepotFiles(fileSpecs, false);
            fileList.forEach(System.out::println);
            
            
            List<IFileSpec> dirList = perforceServer.getDirectories(fileSpecs, null);
            
            dirList.forEach(System.out::println);
            
            System.out.println("");
            IDepot depot = perforceServer.getDepot("localization");
            System.out.println(depot.getMap());*/

        } catch (Exception e) {
            logger.error("Fail to check perforce path: {}", path, e);
            return false;
        } 
        
        return true; 
    }

}
